﻿using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;


namespace Db7.Collections
{
    public class Tags
    {
        private Dictionary<string, bool?> _dict = new Dictionary<string, bool?>();
        public Dictionary<string, GetSetTag> ReservedProperties;

        public Dictionary<string, GetSetTag> ReservedPropertiesNN
        {
            get
            {
                if (ReservedProperties == null) ReservedProperties = new Dictionary<string, GetSetTag>();
                return ReservedProperties;
            }
        }

#if SS_Workaround
        public List<Action<string, bool?>> OnSetKey;
        public List<Action<string, bool?>> OnSetKeyNN
        {
            get
            {
                if (OnSetKey == null) OnSetKey = new List<Action<string, bool?>>();
                return OnSetKey;
            }

        }
#else
        public Action<string, bool?> OnSetKey;
#endif

        private void NotifySubscribers(string key, bool? value)
        {
            if (this.OnSetKey != null)
            {
#if SS_Workaround
                List<Action<string, bool?>> actions = this.OnSetKey;
#else
                var actions = this.OnSetKey.GetInvocationList();
#endif
                foreach (Action<string, bool?> action in actions)
                {
                    action(key, value);
                }
            }
        }

        private void SetKey(string key, bool? value)
        {
            if (ReservedProperties != null && ReservedProperties.ContainsKey(key))
            {
                ReservedProperties[key].Set(value);
            }
            else
            {
                _dict[key] = value;
            }
            //NotifySubscribers(key, value);

        }

        private bool? GetValue(string key)
        {
            if (ReservedProperties != null)
            {
                if (ReservedProperties.ContainsKey(key))
                {
                    GetSetTag gsp = ReservedProperties[key];
                    return gsp.Get();
                }
            }
            if (_dict.ContainsKey(key))
            {
                return _dict[key];
            }
            return null;
        }

        [IntrinsicProperty]
        public bool? this[string key]
        {
            get { return GetValue(key); }
            set { SetKey(key, value); }
        }

        public override string ToString()
        {
            StringBuilder sw = new StringBuilder();
            bool first = true;
            string space = " ";
            string y = "y_";
            string n = "n_";
            foreach (KeyValuePair<string, bool?> kvp in this._dict)
            {
                if (!first) sw.Append(space);
                first = false;
                switch (kvp.Value)
                {
                    case true:
                        sw.Append(y);
                        break;
                    case false:
                        sw.Append(n);
                        break;
                }
                sw.Append(kvp.Key);
            }
            if (this.ReservedProperties != null)
            {
                foreach (KeyValuePair<string, GetSetTag> kvp in this.ReservedProperties)
                {
                    if (!first) sw.Append(space);
                    first = false;
                    switch (kvp.Value.Get())
                    {
                        case true:
                            sw.Append(y);
                            break;
                        case false:
                            sw.Append(n);
                            break;
                    }
                    sw.Append(kvp.Key);
                }
            }
            return sw.ToString();
        }
    }

#if SS_Workaround
    public class GetSetTag
    {
        public Action<bool?> Set;
        public Func<bool?> Get;
    }
#else
    public class GetSetPair<TValue>
    {
        public Action<TValue> Set;
        public Func<TValue> Get;
    }
#endif
}
